#include <chrono>
#include <ctime>
#include <crow.h>
#include <crow/mustache.h>
#include <iostream>
#include <vector>
#include <map>
#include <inja.hpp>



int main() {
    crow::SimpleApp app;

    // Set up inja with a template directory (optional, but good practice)
    //inja::Environment env{"templates/"};

/*
    // Serve static files - Manual static file serving
    CROW_ROUTE(app, "/static/<path>")
    ([](const crow::request& req, crow::response& res, std::string path) {
        // Prevent directory traversal
        if (path.find("..") != std::string::npos) {
            res.code = 403;
            res.end("Forbidden");
            return;
        }

        // Build the full file path
        std::string file_path = "static/" + path;
        
        // Serve the file
        res.set_static_file_info(file_path);
        res.end();
    });
*/
  CROW_ROUTE(app, "/")
  ([]() {
    return "<!DOCTYPE html><html><body><h1>Hello World!</h1></body></html>";
  });

  CROW_ROUTE(app, "/time")
  ([]() {
    std::chrono::system_clock::time_point now =
        std::chrono::system_clock::now();
    time_t tt = std::chrono::system_clock::to_time_t(now);
    // tm utc_tm = *gmtime(&tt);
    tm local_tm = *localtime(&tt);

    auto page = crow::mustache::load("time.html");

    crow::mustache::context ctx({{"year", local_tm.tm_year + 1900},
                                 {"month", local_tm.tm_mon + 1},
                                 {"day", local_tm.tm_mday},
                                 {"hour", local_tm.tm_hour},
                                 {"min", local_tm.tm_min},
                                 {"sec", local_tm.tm_sec}});
    return page.render(ctx);
  });



  //=============================================================
    // A more advanced example using template files and loops
    CROW_ROUTE(app, "/users")
    ([]{
        inja::Environment env{"temp_inja/"};

        nlohmann::json data;
        data["title"] = "User List";
        data["users"] = {"Alice", "Bob", "Charlie"};

        // Render the template from a file "user_list.html"
        //std::string result = env.render("user_list.html", data);
        std::string result = env.render_file("user_list.html", data);
        std::cout << "user_list html:"<< result << std::endl;
        auto res = crow::response(result);
        res.set_header("Content-Type", "text/html");
        return res;
    });

    CROW_ROUTE(app, "/inja")([](){
    inja::Environment env;
    
    nlohmann::json data;
    data["title"] = "Inja Template";
    data["name"] = "C++ World";
    data["items"] = {"Item 1", "Item 2", "Item 3"};
    data["show_feature"] = true;
    
    std::string template_content = R"(
        <html>
        <body>
            <h1>Hello, {{ name }}!</h1>
            {% if show_feature %}
            <p>Special feature is enabled!</p>
            {% endif %}
            <ul>
            {% for item in items %}
                <li>{{ item }}</li>
            {% endfor %}
            </ul>
        </body>
        </html>
    )";
    
    std::string result = env.render(template_content, data);// inja can process template from string directly
    return crow::response(result);
  });

  CROW_ROUTE(app, "/<string>")//can't put before /users route, or else all /users requests go here
  ([](std::string name) {
    auto page = crow::mustache::load("hello.html");
    crow::mustache::context ctx({{"person", name}});
    return page.render(ctx);
  });


    // Custom 404 handler
    CROW_CATCHALL_ROUTE(app)([](){
        crow::mustache::context ctx;
        ctx["title"] = "Page Not Found";
        ctx["message"] = "The page you're looking for doesn't exist.";
        auto page = crow::mustache::load("404.html");
        return page.render();
    });

    //std::cout << "Server running on http://127.0.0.1:8008\n";
    app.port(8080).multithreaded().run();
}
